#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
#include <vector>
#include <string>
#include <memory>
#include <iostream>
#include <fstream>
#include <filesystem>
#include <MidiFile.h>
#include <Options.h>

const int WINDOW_WIDTH = 1200;
const int WINDOW_HEIGHT = 800;
const int PIANO_KEYS = 52; // 4个八度+4个键
const int KEY_WIDTH = 20;
const int WHITE_KEY_HEIGHT = 120;
const int BLACK_KEY_HEIGHT = 80;

struct Note {
    int key;
    float y;
    bool active;
    Note(int k) : key(k), y(0), active(true) {}
};

struct MusicNote {
    int key;
    int duration;  // 持续时间（毫秒）
    MusicNote(int k, int d) : key(k), duration(d) {}
};

class Piano;

static Uint32 resetKeyState(Uint32 interval, void* param);

class Piano {
private:
    SDL_Window* window;
    SDL_Renderer* renderer;
    std::vector<Note> falling_notes;
    std::vector<bool> key_states;
    std::vector<Mix_Chunk*> piano_sounds;
    bool running;
    bool auto_play;
    std::vector<MusicNote> music_sequence;
    size_t current_note;
    Uint32 last_note_time;
    std::string current_music_file;
    float playback_speed;
    
    friend Uint32 resetKeyState(Uint32 interval, void* param);

    // 将MIDI音符转换为我们的键位
    int midiNoteToKey(int midiNote) {
        // MIDI音符范围是0-127，我们需要将其映射到我们的52个键位上
        // 这里假设MIDI音符60（中央C）对应我们的键位24
        int baseNote = midiNote - 60 + 24;
        if (baseNote < 0) baseNote = 0;
        if (baseNote >= PIANO_KEYS) baseNote = PIANO_KEYS - 1;
        return baseNote;
    }

public:
    bool loadMidiFile(const std::string& filename) {
        // 处理文件路径中的引号
        std::string cleanPath = filename;
        if (cleanPath.front() == '\'' && cleanPath.back() == '\'') {
            cleanPath = cleanPath.substr(1, cleanPath.length() - 2);
        }
        
        smf::MidiFile midifile;
        if (!std::filesystem::exists(cleanPath)) {
            std::cerr << "MIDI文件不存在: " << cleanPath << std::endl;
            return false;
        }
        
        midifile.read(cleanPath);
        if (midifile.status() != 1) {
            std::cerr << "无法加载MIDI文件: " << cleanPath << "\n错误信息: 文件格式不正确或文件损坏" << std::endl;
            return false;
        }

        music_sequence.clear();
        current_note = 0;
        last_note_time = 0;
        current_music_file = filename;

        midifile.doTimeAnalysis();
        midifile.linkNotePairs();

        double tpq = midifile.getTicksPerQuarterNote();
        for (int track = 0; track < midifile.getTrackCount(); track++) {
            for (int event = 0; event < midifile[track].size(); event++) {
                if (midifile[track][event].isNoteOn()) {
                    int key = midiNoteToKey(midifile[track][event].getKeyNumber());
                    double duration = midifile[track][event].getDurationInSeconds() * 1000; // 转换为毫秒
                    music_sequence.emplace_back(key, static_cast<int>(duration));
                }
            }
        }

        // 按时间顺序排序音符
        std::sort(music_sequence.begin(), music_sequence.end(),
                 [](const MusicNote& a, const MusicNote& b) {
                     return a.duration < b.duration;
                 });

        auto_play = !music_sequence.empty();
        return true;
    }

public:
    Piano() : window(nullptr), renderer(nullptr), running(true), auto_play(false),
             current_note(0), last_note_time(0) {
        if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
            std::cerr << "SDL初始化失败: " << SDL_GetError() << std::endl;
            return;
        }

        if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
            std::cerr << "音频初始化失败: " << Mix_GetError() << std::endl;
            return;
        }

        key_states.resize(PIANO_KEYS, false);
        loadSounds();
        initMusicSequence();
    }
    
    void initMusicSequence() {
        // 示例音乐序列：小星星（调整到更合适的音域）
        std::vector<std::pair<int, int>> melody = {
            {24, 500}, {24, 500}, {31, 500}, {31, 500},  // 1 1 5 5
            {33, 500}, {33, 500}, {31, 1000},           // 6 6 5
            {29, 500}, {29, 500}, {28, 500}, {28, 500},  // 4 4 3 3
            {26, 500}, {26, 500}, {24, 1000}            // 2 2 1
        };
        
        for (const auto& note : melody) {
            music_sequence.emplace_back(note.first, note.second);
        }
    }
    
    void loadSounds() {
        std::string sound_dir = "sounds/";
        for (int i = 0; i < PIANO_KEYS; ++i) {
            std::string filename = sound_dir + "piano_" + std::to_string(i) + ".wav";
            Mix_Chunk* sound = Mix_LoadWAV(filename.c_str());
            if (sound) {
                Mix_VolumeChunk(sound, MIX_MAX_VOLUME / 2);
                std::cout << "成功加载音频文件: " << filename << std::endl;
            } else {
                std::cerr << "无法加载音频文件: " << filename << "\n错误信息: " << Mix_GetError() << std::endl;
            }
            piano_sounds.push_back(sound);
        }
        
        // 检查是否有音频文件被成功加载
        bool any_sound_loaded = false;
        for (const auto& sound : piano_sounds) {
            if (sound != nullptr) {
                any_sound_loaded = true;
                break;
            }
        }
        
        if (!any_sound_loaded) {
            std::cerr << "警告：没有任何音频文件被成功加载！请检查sounds目录是否存在且包含正确的音频文件。" << std::endl;
        }
    }
    
    bool init() {
        window = SDL_CreateWindow("钢琴演奏", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
        if (!window) {
            std::cerr << "窗口创建失败: " << SDL_GetError() << std::endl;
            return false;
        }
        
        renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
        if (!renderer) {
            std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl;
            return false;
        }
        
        return true;
    }
    
    void render() {
        SDL_SetRenderDrawColor(renderer, 20, 20, 30, 255);
        SDL_RenderClear(renderer);
        
        // 渲染顶部控制栏
        SDL_SetRenderDrawColor(renderer, 40, 40, 60, 255);
        SDL_Rect controlBar = {0, 0, WINDOW_WIDTH, 50};
        SDL_RenderFillRect(renderer, &controlBar);
        
        // 渲染播放速度显示
        char speedText[32];
        snprintf(speedText, sizeof(speedText), "%d%%", static_cast<int>(playback_speed * 100));
        
        // 渲染白键
        int x_offset = (WINDOW_WIDTH - PIANO_KEYS * KEY_WIDTH) / 2;
        int y_offset = WINDOW_HEIGHT - WHITE_KEY_HEIGHT;
        
        for (int i = 0; i < PIANO_KEYS; ++i) {
            SDL_Rect key = {
                x_offset + i * KEY_WIDTH,
                y_offset,
                KEY_WIDTH - 1,
                WHITE_KEY_HEIGHT
            };
            
            if (key_states[i]) {
                SDL_SetRenderDrawColor(renderer, 180, 180, 200, 255);
            } else {
                SDL_SetRenderDrawColor(renderer, 240, 240, 245, 255);
            }
            
            SDL_RenderFillRect(renderer, &key);
        }
        
        // 渲染黑键
        for (int i = 0; i < PIANO_KEYS; ++i) {
            if (i % 7 != 2 && i % 7 != 6) {
                SDL_Rect key = {
                    x_offset + i * KEY_WIDTH + KEY_WIDTH / 2,
                    y_offset,
                    KEY_WIDTH - 2,
                    BLACK_KEY_HEIGHT
                };
                
                if (key_states[i]) {
                    SDL_SetRenderDrawColor(renderer, 40, 40, 50, 255);
                } else {
                    SDL_SetRenderDrawColor(renderer, 20, 20, 30, 255);
                }
                
                SDL_RenderFillRect(renderer, &key);
            }
        }
        
        // 渲染下落的音符
        for (const auto& note : falling_notes) {
            if (note.active) {
                if (note.key % 7 != 2 && note.key % 7 != 6) {
                    SDL_SetRenderDrawColor(renderer, 0, 150, 255, 255);
                } else {
                    SDL_SetRenderDrawColor(renderer, 0, 255, 150, 255);
                }
                SDL_Rect note_rect = {
                    x_offset + note.key * KEY_WIDTH,
                    static_cast<int>(note.y),
                    KEY_WIDTH - 1,
                    10
                };
                SDL_RenderFillRect(renderer, &note_rect);
            }
        }
        
        SDL_RenderPresent(renderer);
    }
    
    void update() {
        // 更新音符位置
        int y_offset = WINDOW_HEIGHT - WHITE_KEY_HEIGHT;
        for (auto& note : falling_notes) {
            if (note.active) {
                note.y += 2.0f;
                if (note.y >= y_offset) {
                    // 当音符接触到键盘时播放声音并设置按键状态
                    if (piano_sounds[note.key]) {
                        Mix_PlayChannel(-1, piano_sounds[note.key], 0);
                    }
                    key_states[note.key] = true;
                    note.active = false;
                    // 设置一个延迟来重置按键状态
                    int current_key = note.key;
                    auto* data = new std::pair<Piano*, int>(this, note.key);
                    SDL_AddTimer(100, resetKeyState, data);
                }
            }
        }
        
        // 自动播放逻辑
        if (auto_play && !music_sequence.empty()) {
            Uint32 current_time = SDL_GetTicks();
            if (current_note < music_sequence.size() && 
                current_time - last_note_time >= music_sequence[current_note].duration) {
                int key = music_sequence[current_note].key;
                
                // 添加下落音符
                falling_notes.emplace_back(key);
                
                // 准备下一个音符
                last_note_time = current_time;
                current_note++;
                
                // 循环播放
                if (current_note >= music_sequence.size()) {
                    current_note = 0;
                }
            }
        }
    }
    
    bool loadMusicFile(const std::string& filename) {
        std::string ext = std::filesystem::path(filename).extension().string();
        if (ext == ".mid" || ext == ".midi") {
            return loadMidiFile(filename);
        } else {
            return loadTextMusicFile(filename);
        }
    }

    bool loadTextMusicFile(const std::string& filename) {
        std::ifstream file(filename);
        if (!file.is_open()) {
            std::cerr << "无法打开文件: " << filename << std::endl;
            return false;
        }

        music_sequence.clear();
        current_note = 0;
        last_note_time = 0;
        current_music_file = filename;

        int key, duration;
        while (file >> key >> duration) {
            if (key >= 0 && key < PIANO_KEYS) {
                music_sequence.emplace_back(key, duration);
            }
        }

        auto_play = !music_sequence.empty();
        return true;
    }

    void handleInput() {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                running = false;
            } else if (event.type == SDL_KEYDOWN) {
                if (event.key.keysym.sym == SDLK_ESCAPE) {
                    running = false;
                    return;
                } else if (event.key.keysym.sym == SDLK_o && (event.key.keysym.mod & KMOD_CTRL)) {
                    // 处理文件选择
                    char filename[256];
                    std::cout << "请输入音乐文件路径: ";
                    std::cin.getline(filename, 256);
                    if (loadMusicFile(filename)) {
                        std::cout << "成功加载音乐文件: " << filename << std::endl;
                    }
                    continue;
                } else if (event.key.keysym.sym == SDLK_SPACE) {
                    // 切换自动播放状态
                    if (!music_sequence.empty()) {
                        auto_play = !auto_play;
                        if (auto_play) {
                            std::cout << "开始播放: " << current_music_file << std::endl;
                        } else {
                            std::cout << "暂停播放: " << current_music_file << std::endl;
                        }
                    }
                    continue;
                }
                // 处理按键事件
                int key = -1;
                switch (event.key.keysym.sym) {
                    // 第一排键位
                    case SDLK_q: key = 0; break;
                    case SDLK_2: key = 1; break;
                    case SDLK_w: key = 2; break;
                    case SDLK_3: key = 3; break;
                    case SDLK_e: key = 4; break;
                    case SDLK_r: key = 5; break;
                    case SDLK_5: key = 6; break;
                    case SDLK_t: key = 7; break;
                    case SDLK_6: key = 8; break;
                    case SDLK_y: key = 9; break;
                    case SDLK_7: key = 10; break;
                    case SDLK_u: key = 11; break;
                    case SDLK_i: key = 12; break;
                    case SDLK_8: key = 13; break;
                    case SDLK_o: key = 14; break;
                    case SDLK_9: key = 15; break;
                    case SDLK_p: key = 16; break;
                    case SDLK_0: key = 17; break;
                    case SDLK_MINUS: key = 18; break;
                    case SDLK_EQUALS: key = 19; break;
                    case SDLK_BACKSPACE: key = 20; break;
                    // 第二排键位
                    case SDLK_a: key = 21; break;
                    case SDLK_s: key = 22; break;
                    case SDLK_d: key = 23; break;
                    case SDLK_f: key = 24; break;
                    case SDLK_g: key = 25; break;
                    case SDLK_h: key = 26; break;
                    case SDLK_j: key = 27; break;
                    case SDLK_k: key = 28; break;
                    case SDLK_l: key = 29; break;
                    case SDLK_SEMICOLON: key = 30; break;
                    case SDLK_QUOTE: key = 31; break;
                    case SDLK_RETURN: key = 32; break;
                    // 第三排键位
                    case SDLK_z: key = 33; break;
                    case SDLK_x: key = 34; break;
                    case SDLK_c: key = 35; break;
                    case SDLK_v: key = 36; break;
                    case SDLK_b: key = 37; break;
                    case SDLK_n: key = 38; break;
                    case SDLK_m: key = 39; break;
                    case SDLK_COMMA: key = 40; break;
                    case SDLK_PERIOD: key = 41; break;
                    case SDLK_SLASH: key = 42; break;
                    case SDLK_RSHIFT: key = 43; break;
                    // 第四排键位
                    case SDLK_SPACE: key = 44; break;
                    case SDLK_RALT: key = 45; break;
                    case SDLK_RCTRL: key = 46; break;
                    case SDLK_LEFT: key = 47; break;
                    case SDLK_DOWN: key = 48; break;
                    case SDLK_RIGHT: key = 49; break;
                    case SDLK_UP: key = 50; break;
                    case SDLK_DELETE: key = 51; break;
                }
                if (key >= 0 && key < PIANO_KEYS) {
                    key_states[key] = true;
                    falling_notes.emplace_back(key);
                    if (piano_sounds[key]) {
                        Mix_PlayChannel(-1, piano_sounds[key], 0);
                    }
                }
            } else if (event.type == SDL_KEYUP) {
                // 处理松开按键事件
                int key = -1;
                switch (event.key.keysym.sym) {
                    // 第一排键位
                    case SDLK_q: key = 0; break;
                    case SDLK_2: key = 1; break;
                    case SDLK_w: key = 2; break;
                    case SDLK_3: key = 3; break;
                    case SDLK_e: key = 4; break;
                    case SDLK_r: key = 5; break;
                    case SDLK_5: key = 6; break;
                    case SDLK_t: key = 7; break;
                    case SDLK_6: key = 8; break;
                    case SDLK_y: key = 9; break;
                    case SDLK_7: key = 10; break;
                    case SDLK_u: key = 11; break;
                    case SDLK_i: key = 12; break;
                    case SDLK_8: key = 13; break;
                    case SDLK_o: key = 14; break;
                    case SDLK_9: key = 15; break;
                    case SDLK_p: key = 16; break;
                    case SDLK_0: key = 17; break;
                    case SDLK_MINUS: key = 18; break;
                    case SDLK_EQUALS: key = 19; break;
                    case SDLK_BACKSPACE: key = 20; break;
                    // 第二排键位
                    case SDLK_a: key = 21; break;
                    case SDLK_s: key = 22; break;
                    case SDLK_d: key = 23; break;
                    case SDLK_f: key = 24; break;
                    case SDLK_g: key = 25; break;
                    case SDLK_h: key = 26; break;
                    case SDLK_j: key = 27; break;
                    case SDLK_k: key = 28; break;
                    case SDLK_l: key = 29; break;
                    case SDLK_SEMICOLON: key = 30; break;
                    case SDLK_QUOTE: key = 31; break;
                    case SDLK_RETURN: key = 32; break;
                    // 第三排键位
                    case SDLK_z: key = 33; break;
                    case SDLK_x: key = 34; break;
                    case SDLK_c: key = 35; break;
                    case SDLK_v: key = 36; break;
                    case SDLK_b: key = 37; break;
                    case SDLK_n: key = 38; break;
                    case SDLK_m: key = 39; break;
                    case SDLK_COMMA: key = 40; break;
                    case SDLK_PERIOD: key = 41; break;
                    case SDLK_SLASH: key = 42; break;
                    case SDLK_RSHIFT: key = 43; break;
                    // 第四排键位
                    case SDLK_SPACE: key = 44; break;
                    case SDLK_RALT: key = 45; break;
                    case SDLK_RCTRL: key = 46; break;
                    case SDLK_LEFT: key = 47; break;
                    case SDLK_DOWN: key = 48; break;
                    case SDLK_RIGHT: key = 49; break;
                    case SDLK_UP: key = 50; break;
                    case SDLK_DELETE: key = 51; break;
                }
                if (key >= 0 && key < PIANO_KEYS) {
                    key_states[key] = false;
                }
            }
        }
    }
    
    void run() {
        while (running) {
            handleInput();
            update();
            render();
            SDL_Delay(16); // 约60FPS
        }
    }
    
    ~Piano() {
        for (auto sound : piano_sounds) {
            if (sound) {
                Mix_FreeChunk(sound);
            }
        }
        if (renderer) {
            SDL_DestroyRenderer(renderer);
        }
        if (window) {
            SDL_DestroyWindow(window);
        }
        Mix_CloseAudio();
        SDL_Quit();
    }
};

static Uint32 resetKeyState(Uint32 interval, void* param) {
    auto data = static_cast<std::pair<Piano*, int>*>(param);
    data->first->key_states[data->second] = false;
    delete data;
    return 0;
}

int main(int argc, char* argv[]) {
    Piano piano;
    if (!piano.init()) {
        return 1;
    }
    
    // 如果提供了MIDI文件路径参数，则加载并播放该文件
    if (argc > 1) {
        if (!piano.loadMidiFile(argv[1])) {
            std::cerr << "无法加载MIDI文件: " << argv[1] << std::endl;
            return 1;
        }
    }
    
    piano.run();
    return 0;
}